package com.lonely.product.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.Assert;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lonely.common.core.domain.BaseEntity;
import com.lonely.common.core.domain.StatusInfo;
import com.lonely.common.core.page.Condition;
import com.lonely.common.enums.DataScope;
import com.lonely.common.threadlocals.DataPermissionThreadLocal;
import com.lonely.common.utils.SecurityUtils;
import com.lonely.common.utils.enums.ExtractStatusInfoUtil;
import com.lonely.deliver.service.IOrderDeliverService;
import com.lonely.order.domain.entity.SysOrder;
import com.lonely.order.domain.entity.SysOrderSplit;
import com.lonely.order.enums.OrderEnum;
import com.lonely.order.service.IOrderService;
import com.lonely.order.service.IOrderSplitService;
import com.lonely.product.domain.dto.postfinishing.PostFinishingCompletedDTO;
import com.lonely.product.domain.dto.postfinishing.QueryOrderPostFinishingPageDTO;
import com.lonely.product.domain.dto.postfinishing.StartPostFinishingDTO;
import com.lonely.product.domain.entity.SysOrderPostFinishing;
import com.lonely.product.domain.entity.SysOrderSewing;
import com.lonely.product.domain.vo.postfinishing.QueryOrderPostFinishingPageVO;
import com.lonely.product.enums.OrderPostFinishingEnum;
import com.lonely.product.enums.OrderSewingEnum;
import com.lonely.product.mapper.SysOrderPostFinishingMapper;
import com.lonely.product.service.IOrderPostFinishingService;
import com.lonely.product.service.IOrderSewingService;
import com.lonely.system.domain.entity.SysFactory;
import com.lonely.system.enums.SysFactoryEnum;
import com.lonely.system.service.ISysFactoryService;
import com.lonely.system.utils.AuthUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author : 黄志标
 * @date: 2025/8/12 9:40
 * @description: 订单后整服务实现类
 */
@Service
@Slf4j
public class OrderPostFinishingServiceImpl extends ServiceImpl<SysOrderPostFinishingMapper, SysOrderPostFinishing> implements IOrderPostFinishingService {

    @Autowired
    private IOrderService orderService;

    @Autowired
    private IOrderSplitService orderSplitService;

    @Autowired
    private ISysFactoryService sysFactoryService;

    @Autowired
    private IOrderDeliverService orderDeliverService;

    @Autowired
    private IOrderSewingService orderSewingService;

    /**
     * 生成订单后整数据
     *
     * @param produceOrderId
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void createOrderPostFinishing(Long produceOrderId) {
        // 判断是否已存在后整数据
        if (isExistOrderPostFinishing(produceOrderId)) {
            log.info("该订单已存在后整数据");
            return;
        }

        // 判断该订单分单状态
        SysOrderSplit tailSplit = this.orderSplitService.getTailSplit(produceOrderId);
        if (tailSplit != null) {
            SysOrderPostFinishing defaultPostFinishing = this.generatorDefaultOrderPostFinishing(produceOrderId);

            // 判断是总厂还是外发厂
            SysFactory sysFactory = this.sysFactoryService.getById(tailSplit.getFactoryId());
            Assert.notNull(sysFactory, "工厂不存在");
            defaultPostFinishing.setFactoryId(sysFactory.getId());

            SysFactoryEnum.FactoryType factoryType = SysFactoryEnum.FactoryType.getInstance(sysFactory.getType());
            if (factoryType == SysFactoryEnum.FactoryType.OWN) {
                defaultPostFinishing.setType(OrderPostFinishingEnum.TypeEnum.GENERAL_FACTORY.getValue());
            }
            if (factoryType == SysFactoryEnum.FactoryType.COOPERATIVE) {
                defaultPostFinishing.setType(OrderPostFinishingEnum.TypeEnum.OUTSOURCING_FACTORY.getValue());
            }

            this.save(defaultPostFinishing);

        } else {
            // 未分单，分别生成总厂后整类型和外发后整的数据
            this.saveUndividedOrderPostFinishing(produceOrderId);
        }

    }

    /**
     * 后整分页查询
     *
     * @param queryDto
     * @return
     */
    @Override
    public Page<QueryOrderPostFinishingPageVO> page(QueryOrderPostFinishingPageDTO queryDto) {
        DataPermissionThreadLocal.setDataPermission(DataScope.ORDER_FACTORY, "o.factory_permission");
        Page<QueryOrderPostFinishingPageVO> page = Condition.page(queryDto);
        return super.getBaseMapper().page(page, queryDto, OrderPostFinishingEnum.TypeEnum.GENERAL_FACTORY.getValue());
    }

    /**
     * 获取状态信息
     *
     * @param queryDto
     * @return
     */
    @Override
    public List<StatusInfo> getStatusInfo(QueryOrderPostFinishingPageDTO queryDto) {
        // 去除状态过滤
        queryDto.setPostFinishingStatus(null);
        // 添加数据权限过滤
        String factoryPermissionsJsonStr = AuthUtil.getLoginUserFactoryPermissionsJsonStr();
        List<StatusInfo> statusTotals = super.getBaseMapper().getStatusTotals(queryDto, OrderPostFinishingEnum.TypeEnum.GENERAL_FACTORY.getValue(), factoryPermissionsJsonStr);
        return ExtractStatusInfoUtil.extractStatusInfos(statusTotals, OrderPostFinishingEnum.StatusEnum.values());
    }

    /**
     * 外发后整分页查询
     *
     * @param queryDto
     * @return
     */
    @Override
    public Page<QueryOrderPostFinishingPageVO> outsourcePage(QueryOrderPostFinishingPageDTO queryDto) {
        DataPermissionThreadLocal.setDataPermission(DataScope.ORDER_FACTORY, "o.factory_permission");
        Page<QueryOrderPostFinishingPageVO> page = Condition.page(queryDto);
        return super.getBaseMapper().page(page, queryDto, OrderPostFinishingEnum.TypeEnum.OUTSOURCING_FACTORY.getValue());
    }

    /**
     * 获取外发后整状态信息
     *
     * @param queryDto
     * @return
     */
    @Override
    public List<StatusInfo> getOutsourceStatusInfo(QueryOrderPostFinishingPageDTO queryDto) {
        // 去除状态过滤
        queryDto.setPostFinishingStatus(null);
        // 添加数据权限过滤
        String factoryPermissionsJsonStr = AuthUtil.getLoginUserFactoryPermissionsJsonStr();
        List<StatusInfo> statusTotals = super.getBaseMapper().getStatusTotals(queryDto, OrderPostFinishingEnum.TypeEnum.OUTSOURCING_FACTORY.getValue(), factoryPermissionsJsonStr);
        return ExtractStatusInfoUtil.extractStatusInfos(statusTotals, OrderPostFinishingEnum.StatusEnum.values());
    }

    /**
     * 开始后整
     *
     * @param requestDto
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void startPostFinishing(StartPostFinishingDTO requestDto) {
        super.update(new LambdaUpdateWrapper<SysOrderPostFinishing>()
                .eq(SysOrderPostFinishing::getId, requestDto.getPostFinishingId())
                .eq(SysOrderPostFinishing::getType, requestDto.getPostFinishingType())
                .eq(SysOrderPostFinishing::getStatus, OrderPostFinishingEnum.StatusEnum.TO_BE_POST_FINISHING.getStatus())
                .set(SysOrderPostFinishing::getStatus, OrderPostFinishingEnum.StatusEnum.IN_POST_FINISHING_SEAM.getStatus())
                .set(SysOrderPostFinishing::getStartPostFinishingQuantity, requestDto.getStartPostFinishingQuantity())
                .set(SysOrderPostFinishing::getPostFinishingStartTime, new Date())
                .set(SysOrderPostFinishing::getUpdateBy, SecurityUtils.getUserId())
        );
    }

    /**
     * 订单尾部分单后置处理
     *
     * @param produceOrderIds
     * @param sysFactory
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void orderTailSplitAfterProcess(List<Long> produceOrderIds, SysFactory sysFactory) {
        if (CollUtil.isEmpty(produceOrderIds)) {
            return;
        }

        // 获取工厂类型
        SysFactoryEnum.FactoryType factoryType = SysFactoryEnum.FactoryType.getInstance(sysFactory.getType());

        // 定义当前工厂类型对应的后整类型和需删除的类型
        OrderPostFinishingEnum.TypeEnum keepType;
        OrderPostFinishingEnum.TypeEnum removeType;
        if (SysFactoryEnum.FactoryType.OWN.equals(factoryType)) {
            // 总厂：保留总厂类型，删除外发类型
            keepType = OrderPostFinishingEnum.TypeEnum.GENERAL_FACTORY;
            removeType = OrderPostFinishingEnum.TypeEnum.OUTSOURCING_FACTORY;
        } else {
            // 外发厂：保留外发类型，删除总厂类型
            keepType = OrderPostFinishingEnum.TypeEnum.OUTSOURCING_FACTORY;
            removeType = OrderPostFinishingEnum.TypeEnum.GENERAL_FACTORY;
        }

        for (Long produceOrderId : produceOrderIds) {
            // 获取当前订单的未完工的后整数据
            List<SysOrderPostFinishing> orderPostFinishings = super.list(new LambdaQueryWrapper<SysOrderPostFinishing>()
                    .eq(SysOrderPostFinishing::getProduceOrderId, produceOrderId)
                    .ne(SysOrderPostFinishing::getStatus, OrderPostFinishingEnum.StatusEnum.COMPLETED.getStatus())
            );
            if (CollUtil.isEmpty(orderPostFinishings)) {
                log.debug("当前订单无未完工的后整数据");
                continue;
            }

            if (CollUtil.size(orderPostFinishings) == 1) {
                // 非未分单状态的后整数据
                SysOrderPostFinishing orderPostFinishing = orderPostFinishings.get(0);

                // 判断是否修改了工厂
                if (Objects.equals(orderPostFinishing.getFactoryId(), sysFactory.getId())) {
                    // 没有改变工厂,不做改变
                    log.debug("当前订单后整数据未改变工厂,不做调整...");
                    continue;
                }

                // 修改了工厂，更新工厂id和重置订单状态
                orderPostFinishing.setFactoryId(sysFactory.getId());
                orderPostFinishing.setType(keepType.getValue());
                orderPostFinishing.setStartPostFinishingQuantity(null);
                orderPostFinishing.setStatus(OrderPostFinishingEnum.StatusEnum.TO_BE_POST_FINISHING.getStatus());
                super.updateById(orderPostFinishing);
            } else {
                // 有多条后整数据，即都是未分单的数据

                // 查找需要保留并更新 factoryId 的后整记录
                SysOrderPostFinishing targetPostFinishing = orderPostFinishings.stream()
                        .filter(x -> Objects.equals(x.getType(), keepType.getValue()))
                        .findFirst()
                        .orElse(null);
                if (targetPostFinishing != null) {
                    targetPostFinishing.setFactoryId(sysFactory.getId());
                    targetPostFinishing.setStatus(OrderPostFinishingEnum.StatusEnum.TO_BE_POST_FINISHING.getStatus());
                    targetPostFinishing.setStartPostFinishingQuantity(null);
                    super.updateById(targetPostFinishing);
                }

                // 收集需要删除的后整 ID（对应 removeType）
                List<Long> idsToRemove = orderPostFinishings.stream()
                        .filter(x -> Objects.equals(x.getType(), removeType.getValue()))
                        .map(BaseEntity::getId)
                        .collect(Collectors.toList());
                if (CollUtil.isNotEmpty(idsToRemove)) {
                    super.removeByIds(idsToRemove);
                }
            }
        }
    }

    /**
     * 后整完工
     *
     * @param requestDto
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void postFinishingCompleted(PostFinishingCompletedDTO requestDto) {
        SysOrderPostFinishing postFinishing = super.getOne(new LambdaQueryWrapper<SysOrderPostFinishing>()
                .eq(SysOrderPostFinishing::getId, requestDto.getPostFinishingId())
                .eq(SysOrderPostFinishing::getType, requestDto.getPostFinishingType())
                .eq(SysOrderPostFinishing::getStatus, OrderPostFinishingEnum.StatusEnum.IN_POST_FINISHING_SEAM.getStatus())
        );
        Assert.notNull(postFinishing, "未找到后整数据");

        // 更新数据
        postFinishing.setCompletedPostFinishingQuantity(requestDto.getCompletedPostFinishingQuantity());
        postFinishing.setStatus(OrderPostFinishingEnum.StatusEnum.COMPLETED.getStatus());
        postFinishing.setPostFinishingEndTime(new Date());
        postFinishing.setUpdateBy(SecurityUtils.getUserId());
        super.updateById(postFinishing);

        // 同步发货单
        SysOrder sysOrder = this.orderService.getById(postFinishing.getOrderId());
        Assert.notNull(sysOrder, "未查询到该后整单对应的订单数据");
        if (Objects.equals(sysOrder.getOrderSource(), OrderEnum.OrderSourceEnum.SHEIN.getOrderSource())) {
            this.orderDeliverService.synchronizerOrderDeliver(ListUtil.of(sysOrder), true);
        }
    }

    /**
     * 获取默认的开始后整数
     * 逻辑：默认取值为该订单对应的车缝管理的车缝数
     *
     * @param postFinishingId
     * @return
     */
    @Override
    public String getDefaultStartPostFinishingQuantity(Long postFinishingId) {
        SysOrderPostFinishing orderPostFinishing = super.getById(postFinishingId);
        Assert.notNull(orderPostFinishing, "未找到该后整数据");

        SysOrderSewing orderSewing = this.orderSewingService.getOne(new LambdaQueryWrapper<SysOrderSewing>()
                .eq(SysOrderSewing::getProduceOrderId, orderPostFinishing.getProduceOrderId())
                .eq(SysOrderSewing::getStatus, OrderSewingEnum.StatusEnum.COMPLETED.getStatus())
        );
        Assert.notNull(orderSewing, "未找到该订单车缝数据");
        return Convert.toStr(orderSewing.getCompletedSewingQuantity());
    }

    /**
     * 获取默认的后整完工数
     * 逻辑: 默认取值为当前后整数
     *
     * @param postFinishingId
     * @return
     */
    @Override
    public String getDefaultCompletedPostFinishingQuantity(Long postFinishingId) {
        SysOrderPostFinishing orderPostFinishing = super.getById(postFinishingId);
        Assert.notNull(orderPostFinishing, "未找到该后整数据");
        return Convert.toStr(orderPostFinishing.getStartPostFinishingQuantity());
    }

    /**
     * 未分单的后整数据入库
     *
     * @param produceOrderId
     */
    private void saveUndividedOrderPostFinishing(Long produceOrderId) {
        // 总厂未分单的后整数据
        SysOrderPostFinishing generalFactoryPostFinishing = this.generatorDefaultOrderPostFinishing(produceOrderId);
        generalFactoryPostFinishing.setType(OrderPostFinishingEnum.TypeEnum.GENERAL_FACTORY.getValue());
        generalFactoryPostFinishing.setStatus(OrderPostFinishingEnum.StatusEnum.UNDIVIDED_ORDERS.getStatus());
        generalFactoryPostFinishing.setFactoryId(null);
        super.save(generalFactoryPostFinishing);

        // 外发厂未分单的后整数据
        SysOrderPostFinishing outsourceFactoryPostFinishing = this.generatorDefaultOrderPostFinishing(produceOrderId);
        outsourceFactoryPostFinishing.setType(OrderPostFinishingEnum.TypeEnum.OUTSOURCING_FACTORY.getValue());
        outsourceFactoryPostFinishing.setStatus(OrderPostFinishingEnum.StatusEnum.UNDIVIDED_ORDERS.getStatus());
        outsourceFactoryPostFinishing.setFactoryId(null);
        super.save(outsourceFactoryPostFinishing);
    }


    /**
     * 构架默认的后整数据
     *
     * @param produceOrderId
     * @return
     */
    private SysOrderPostFinishing generatorDefaultOrderPostFinishing(Long produceOrderId) {
        SysOrder sysOrder = this.orderService.getOne(new LambdaQueryWrapper<SysOrder>().eq(SysOrder::getProduceOrderId, produceOrderId));
        Assert.notNull(sysOrder, "订单不存在");

        SysOrderPostFinishing orderPostFinishing = new SysOrderPostFinishing();
        orderPostFinishing.setOrderId(sysOrder.getId());
        orderPostFinishing.setProduceOrderId(Convert.toStr(produceOrderId));
        orderPostFinishing.setType(null);
        orderPostFinishing.setFactoryId(null);
        orderPostFinishing.setPostFinishingStartTime(null);
        orderPostFinishing.setPostFinishingEndTime(null);
        orderPostFinishing.setCreateBy(SecurityUtils.getUserId());
        orderPostFinishing.setUpdateBy(SecurityUtils.getUserId());
        return orderPostFinishing;
    }


    /**
     * 判断是否已存在后整数据
     *
     * @param produceOrderId
     * @return
     */
    private boolean isExistOrderPostFinishing(Long produceOrderId) {
        int count = super.count(new LambdaQueryWrapper<SysOrderPostFinishing>()
                .eq(SysOrderPostFinishing::getProduceOrderId, produceOrderId)
        );
        return count > 0;
    }

}
